#ifdef ARCTIC
/**
 @file sys_at_queue_shape.c

 @date 2021-8-13

 @version v1.0

 The file contains AT QoS queue schedule APIs of sys layer
*/

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "sys_usw_common.h"
#include "sys_usw_chip.h"
#include "sys_usw_qos.h"
#include "sys_at_qos.h"
#include "drv_api.h"


#define SYS_SHAPE_DEFAULT_RATE              0xFFFFFFFC
#define SYS_SHAPE_DEFAULT_THRD              267386
#define SYS_QOS_SHAPE_MAX_ECNMARK_RATE     800000000

extern int32
sys_at_qos_set_port_shp_base_pkt_en(uint8 lchip, uint32 gport, uint8 enable);

#define __SHAPE__
int32
_sys_at_shape_qos_get_shp_gran(uint8 lchip, uint32 rate, /*kb/s*/
                                                       uint8 is_pps,
                                                       uint8 *gran_lvl,
                                                       uint32 *sw_gran,
                                                       uint32 *bucket_cnt_gran)
{
    uint8 index = 0;
    uint32 token_rate_Mbps = rate / 1000;

    /*per byte use token num
    * rate gran : update_freq / byte_bucket_cnt_gran (byte/s)
    * thrd gran : (1 << 16) / byte_bucket_cnt_gran (byte)
    */
    uint32 byte_bucket_cnt_gran[8] = {256,128,64,32,16,8,4,2};
    uint32 byte_bucket_cnt_gran_lvl[8] = {0,1,2,3,4,5,6,7};
    /*per pkt use token num
    * pps rate gran : update_freq / pkt_bucket_cnt_gran (pps)
    * pps thrd gran : (1 << 16) / pkt_bucket_cnt_gran (pkt)
    */
    uint32 pkt_bucket_cnt_gran[8] = {32000,16000,8000,4000,2000,1000,500,250};

    /*max pps rate per rate gran*/
    uint32 rate_gran_interval_pps[8] = {10000000,20000000,40000000,80000000,160000000,320000000, 640000000,1280000000};

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    for (index = 0; index < 8; index++)
    {
        if (is_pps && (rate <= rate_gran_interval_pps[index]))
        {
            *gran_lvl = index;
            *bucket_cnt_gran = pkt_bucket_cnt_gran[index];
            break;
        }
        else if (!is_pps && token_rate_Mbps <= p_usw_queue_master[lchip]->que_shp_gran[index].max_rate)
        {
            *sw_gran = p_usw_queue_master[lchip]->que_shp_gran[index].granularity;
            *gran_lvl = byte_bucket_cnt_gran_lvl[index];
            *bucket_cnt_gran = byte_bucket_cnt_gran[index];
            break;
        }
    }

    return CTC_E_NONE;
}
int32
sys_at_shape_map_profile_user_to_hw(uint8 lchip, uint32 user_rate, uint32 user_bucket_thrd,
                                                              uint8 is_pps, uint8 *gran_lvl, uint32 *hw_rate, uint32 *hw_bucket_thrd)
{
    uint32 bucket_cnt_gran = 0;
    uint32 sw_gran = 1;
    uint64 bucket_thrd = 0;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    _sys_at_shape_qos_get_shp_gran(lchip, user_rate, is_pps, gran_lvl, &sw_gran, &bucket_cnt_gran);

    user_rate  = (user_rate / sw_gran) * sw_gran;
    if (is_pps)
    {
       *hw_rate = user_rate / (p_usw_queue_master[lchip]->que_shp_update_freq / bucket_cnt_gran);
    }
    else
    {
        *hw_rate = user_rate / (p_usw_queue_master[lchip]->que_shp_update_freq / bucket_cnt_gran * 8 / 1000);
    }
    if (0 == user_bucket_thrd)
    {
        bucket_thrd = (*hw_rate / bucket_cnt_gran + SYS_QOS_MTU) * 5;
    }
    else
    {
        bucket_thrd = is_pps ? user_bucket_thrd : user_bucket_thrd * 125;
    }

    bucket_thrd = (bucket_thrd * bucket_cnt_gran) >> 16;
    *hw_bucket_thrd = ((*hw_rate == 0) && (0 == user_bucket_thrd)) ? 0 : (bucket_thrd == 0 ? 1 : bucket_thrd);

    if(*hw_rate > MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE))
    {
        *hw_rate = MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE);
    }

    if(*hw_bucket_thrd > MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD))
    {
        *hw_bucket_thrd = MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD);
    }

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " is_pps : %d\n",  is_pps);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " gran_lvl : %d\n",  *gran_lvl);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " hw_rate : %d\n",  *hw_rate);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " hw_bucket_thrd : %d\n",  *hw_bucket_thrd);

    return CTC_E_NONE;
}
int32
sys_at_shape_map_profile_hw_to_user(uint8 lchip, uint32 hw_rate, uint32 hw_bucket_thrd,
                                                              uint8 is_pps, uint8 gran_lvl, uint32 *user_rate, uint32 *user_bucket_thrd)
{
    uint32 bucket_cnt_gran = 0;
    uint32 byte_bucket_cnt_gran[8] = {256,128,64,32,16,8,4,2};
    uint32 pkt_bucket_cnt_gran[8] = {32000,16000,8000,4000,2000,1000,500,250};

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    bucket_cnt_gran = is_pps ? pkt_bucket_cnt_gran[gran_lvl] : byte_bucket_cnt_gran[gran_lvl];

    if (is_pps)
    {
        *user_rate = hw_rate * (p_usw_queue_master[lchip]->que_shp_update_freq / bucket_cnt_gran);
        *user_bucket_thrd = (hw_bucket_thrd << 16) / bucket_cnt_gran;
    }
    else
    {
        *user_rate = hw_rate * (p_usw_queue_master[lchip]->que_shp_update_freq / bucket_cnt_gran * 8 / 1000);
        *user_bucket_thrd = (hw_bucket_thrd << 16) / bucket_cnt_gran * 8 / 1000;
    }

    return CTC_E_NONE;
}

int32
sys_at_shape_add_que_shp_to_asic(uint8 lchip, sys_queue_node_t* p_queue_node, void* p_shape, uint8 is_pps)
{
    ctc_qos_shape_queue_t* p_que_shape = (ctc_qos_shape_queue_t*)p_shape;
    ds_t ds;
    uint32 cmd = 0;
    uint32 token_rate = 0;
    uint32 token_threshold = 0;
    uint32 token_rate_cir = 0;
    uint32 token_threshold_cir = 0;
    uint8  group_id = 0;
    uint8  gran_lvl = 0;
    uint8  gran_lvl_cir = 0;
    uint8  prof_step = 0;
    uint8  token_step = 0;
    uint8  need_pp_en = 1;
    uint8 is_eunit_queue = SYS_QUEUE_TYPE_EUNIT == p_queue_node->type;
    uint8 queue_offset = 0;


    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_QOS_LCHIP_CONVERT(lchip, p_queue_node->pp_id);
    /*get rate*/
    if (p_que_shape->enable)
    {
        sys_at_shape_map_profile_user_to_hw(lchip, p_que_shape->pir, p_que_shape->pbs,
                                             is_pps, &gran_lvl, &token_rate, &token_threshold);
        sys_at_shape_map_profile_user_to_hw(lchip, p_que_shape->cir, p_que_shape->cbs,
                                             is_pps, &gran_lvl_cir, &token_rate_cir, &token_threshold_cir);
    }
    else
    {
        token_rate = MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE);
        token_threshold = MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD);
        gran_lvl = 7;
        token_rate_cir = 0;
        token_threshold_cir= 0;
        gran_lvl_cir= 0;
    }
    if (CTC_QUEUE_TYPE_EXCP_CPU == p_que_shape->queue.queue_type
        && !is_eunit_queue)
    {
        need_pp_en = 0;
    }

    if (is_eunit_queue)
    {
        group_id = SYS_DMA_SUB_CHAN; /*dma sub channel id*/
        queue_offset = p_queue_node->offset / MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
    }
    else if (SYS_QUEUE_TYPE_EXCP == p_queue_node->type || SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type) /*DMA mcQ*/
    {
        SYS_AT_GROUP_ID(group_id, p_queue_node);
        queue_offset =  p_queue_node->offset % MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
    }
    else
    {
        SYS_AT_GROUP_ID(group_id, p_queue_node);
        queue_offset = p_queue_node->offset;
    }

    prof_step = DsQMgrCosGrpShpProfile_g_1_shpProfile_tokenRate_f - DsQMgrCosGrpShpProfile_g_0_shpProfile_tokenRate_f;
    token_step = DsQMgrCosGrpShpToken_g_1_shpToken_token_f - DsQMgrCosGrpShpToken_g_0_shpToken_token_f;

    /*pir*/
    cmd = DRV_IOR(DsQMgrCosGrpShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));
    SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenRate_f + prof_step * queue_offset, &ds, token_rate);
    SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenThrd_f + prof_step * queue_offset, &ds, token_threshold);
    SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenGran_f + prof_step * queue_offset, &ds, gran_lvl);
    //SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_ppsMode_f + prof_step * queue_offset, &ds, is_pps);
    cmd = DRV_IOW(DsQMgrCosGrpShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));

    cmd = DRV_IOR(DsQMgrCosGrpShpToken_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));
    SetDsQMgrCosGrpShpToken(V, g_0_shpToken_token_f + token_step * queue_offset, &ds, 0);
    cmd = DRV_IOW(DsQMgrCosGrpShpToken_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));

    if (SYS_QUEUE_TYPE_NORMAL == p_queue_node->type || is_eunit_queue)
    {
        /*cir*/
        prof_step = DsQMgrCosGrpShpProfile0_g_1_shpProfile0_tokenGran_f - DsQMgrCosGrpShpProfile0_g_0_shpProfile0_tokenGran_f;
        token_step = DsQMgrCosGrpShpToken0_g_1_shpToken0_token_f - DsQMgrCosGrpShpToken0_g_0_shpToken0_token_f;

        cmd = DRV_IOR(DsQMgrCosGrpShpProfile0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));
        SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenRate_f + prof_step * queue_offset, &ds, token_rate_cir);
        SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenThrd_f + prof_step * queue_offset, &ds, token_threshold_cir);
        SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenGran_f + prof_step * queue_offset, &ds, gran_lvl_cir);
        //SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_ppsMode_f + prof_step * queue_offset, &ds, is_pps);
        cmd = DRV_IOW(DsQMgrCosGrpShpProfile0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));

        cmd = DRV_IOR(DsQMgrCosGrpShpToken0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));
        SetDsQMgrCosGrpShpToken0(V, g_0_shpToken0_token_f + token_step * queue_offset, &ds, 0);
        cmd = DRV_IOW(DsQMgrCosGrpShpToken0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, need_pp_en ? DRV_CMD_PP_EN(cmd) : cmd, &ds));
    }
    return CTC_E_NONE;
}

int32
sys_at_shape_add_chan_shp_to_asic(uint8 lchip, uint16 channel, uint32 pir, uint32 pbs,
                                                           uint8 is_pps, uint8 enable)
{
    uint32 cmd = 0;
    uint32 token_rate = 0;
    uint32 token_threshold = 0;
    uint32 value = 0;
    uint8  gran_lvl = 0;
    DsQMgrPortShpProfile_m port_shp_profile;
    uint16 sub_chan = 0;
    uint16 pp_chan = 0;
    uint16 que_idx = 0;
    uint16 que_base = 0;
    DsQMgrQueCreditBucket_m ds_bucket;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sal_memset(&port_shp_profile, 0, sizeof(DsQMgrPortShpProfile_m));

    sys_at_shape_map_profile_user_to_hw(lchip, pir, pbs, is_pps, &gran_lvl, &token_rate, &token_threshold);

    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    pp_chan = SYS_PP_CHAN_BY_SUB_CHAN(sub_chan);

    cmd = DRV_IOR(DsQMgrPortShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &port_shp_profile));

    if (!enable)
    {
        token_rate = MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE);
        token_threshold = MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD);
        gran_lvl = 7;
    }

    //SetDsQMgrPortShpProfile(V, ppsMode_f, &port_shp_profile, is_pps);
    SetDsQMgrPortShpProfile(V, tokenGran_f  , &port_shp_profile, gran_lvl);
    SetDsQMgrPortShpProfile(V, tokenRate_f, &port_shp_profile, token_rate);
    SetDsQMgrPortShpProfile(V, tokenThrd_f  , &port_shp_profile, token_threshold);

    cmd = DRV_IOW(DsQMgrPortShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &port_shp_profile));

    cmd = DRV_IOW(DsQMgrPortShpToken_t, DsQMgrPortShpToken_token_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &value));
    que_base = pp_chan * MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
    sal_memset(&ds_bucket, 0, sizeof(ds_bucket));

    for (que_idx = que_base; que_idx < (que_base + MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN)); que_idx++)
    {
        cmd = DRV_IOW(DsQMgrQueCreditBucket_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, que_idx, DRV_CMD_PP_EN(cmd), &ds_bucket));
        cmd = DRV_IOW(DsQMgrQueCreditBucket0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, que_idx, DRV_CMD_PP_EN(cmd), &ds_bucket));
    }

    if (MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0) == channel)
    {
        /*reset DMA 128mcQ & 32ucQ */
        for (que_idx = 624; que_idx < (que_base + 128 + 32); que_idx++)
        {
            cmd = DRV_IOW(DsQMgrQueCreditBucket_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, que_idx, DRV_CMD_PP_EN(cmd), &ds_bucket));
            cmd = DRV_IOW(DsQMgrQueCreditBucket0_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, que_idx, DRV_CMD_PP_EN(cmd), &ds_bucket));
        }
    }
    return CTC_E_NONE;
}


int32
_sys_at_shape_init_queue_shp(uint8 lchip)
{
    uint32 cmd = 0;
    uint32 max_size = 0;
    uint16 index = 0;
    uint16 step = 0;
    DsQMgrCosGrpShpProfile_m cos_profile;
    QMgrQueGrpShpCtl_m que_shp_ctl;

    sal_memset(&cos_profile, 0, sizeof(cos_profile));
    sal_memset(&que_shp_ctl, 0, sizeof(que_shp_ctl));

    /* default disable queue shape*/
    step = DsQMgrCosGrpShpProfile_g_1_shpProfile_tokenGran_f - DsQMgrCosGrpShpProfile_g_0_shpProfile_tokenGran_f;
    for (index = 0; index < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_GRP); index++)
    {
        SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenGran_f + index * step, &cos_profile, 7);
        SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenRate_f + index * step, &cos_profile, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE));
        SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenThrd_f + index * step, &cos_profile, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD));
    }

    sys_usw_ftm_query_table_entry_num(lchip, DsQMgrCosGrpShpProfile_t, &max_size);
    for (index = 0; index < max_size; index++)
    {
        cmd = DRV_IOW(DsQMgrCosGrpShpProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, cmd, &cos_profile));
    }

    SetQMgrQueGrpShpCtl(V, shpPtrMin_f, &que_shp_ctl, 0);
    SetQMgrQueGrpShpCtl(V, shpRefreshDis_f, &que_shp_ctl, 0);
    SetQMgrQueGrpShpCtl(V, shpTickInterval_f, &que_shp_ctl, 1);
    SetQMgrQueGrpShpCtl(V, shpPtrMax_f, &que_shp_ctl, SYS_AT_NETWORK_GROUP_NUM + SYS_AT_DMA_GROUP_NUM_MC - 1);
    cmd = DRV_IOW(QMgrQueGrpShpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &que_shp_ctl));

    return CTC_E_NONE;
}
int32
_sys_at_shape_init_group_shp(uint8 lchip)
{
    uint32 cmd = 0;
    uint16 index = 0;
    uint8  step = 0;
    DsQMgrL0NodeShpProfile_m grp_node_shp_profile;
    QMgrL0ShpCtl_m grp_shp_ctl;

    sal_memset(&grp_node_shp_profile, 0, sizeof(grp_node_shp_profile));
    sal_memset(&grp_shp_ctl, 0, sizeof(grp_shp_ctl));

    /* default disable L0 node shape*/
    step = DsQMgrL0NodeShpProfile_g_1_shpProfile_ppsMode_f - DsQMgrL0NodeShpProfile_g_0_shpProfile_ppsMode_f;
    for (index = 0; index < MCHIP_CAP(SYS_CAP_QOS_LX_GRP_NODE_NUM) ; index++)
    {
        SetDsQMgrL0NodeShpProfile(V, g_0_shpProfile_tokenRate_f + index * step, &grp_node_shp_profile, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE));
        SetDsQMgrL0NodeShpProfile(V, g_0_shpProfile_tokenThrd_f + index * step, &grp_node_shp_profile, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD));
        SetDsQMgrL0NodeShpProfile(V, g_0_shpProfile_tokenGran_f + index * step, &grp_node_shp_profile, 7);
    }
    cmd = DRV_IOW(DsQMgrL0NodeShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &grp_node_shp_profile));

    /* cfg grp shp scan*/
    SetQMgrL0ShpCtl(V, shpPtrMin_f, &grp_shp_ctl, 0);
    SetQMgrL0ShpCtl(V, shpRefreshDis_f, &grp_shp_ctl, 0);
    SetQMgrL0ShpCtl(V, shpTickInterval_f, &grp_shp_ctl, 1);
    SetQMgrL0ShpCtl(V, shpPtrMax_f, &grp_shp_ctl, 1);
    cmd = DRV_IOW(QMgrL0ShpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &grp_shp_ctl));

    return CTC_E_NONE;
}

int32
_sys_at_shape_init_chan_shp(uint8 lchip)
{
    uint16 channel_id              = 0;
    uint32 cmd                     = 0;
    DsQMgrPortShpProfile_m chan_shp_profile;
    QMgrPortShpCtl_m port_shp_ctl;
    DsEpeHeaderEditChanAqmScanCtl_m aqm_port_scan_ctl;
    EpeHeaderEditChanAqmUpdateCtl_m aqm_port_update_ctl;
    EpeHdrAdjustCtl_m epe_hdr_ctl;
    QMgrRdPktUnitCtl_m pkt_unit;

    sal_memset(&chan_shp_profile, 0, sizeof(chan_shp_profile));
    sal_memset(&port_shp_ctl, 0, sizeof(port_shp_ctl));
    sal_memset(&aqm_port_scan_ctl, 0, sizeof(aqm_port_scan_ctl));
    sal_memset(&aqm_port_update_ctl, 0, sizeof(aqm_port_update_ctl));

    /* default disable chan shape*/
    SetDsQMgrPortShpProfile(V, tokenRate_f, &chan_shp_profile, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE));
    SetDsQMgrPortShpProfile(V, tokenThrd_f, &chan_shp_profile, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD));
    SetDsQMgrPortShpProfile(V, tokenGran_f, &chan_shp_profile, 7);

    for (channel_id = 0; channel_id < 52; channel_id++)
    {
        cmd = DRV_IOW(DsQMgrPortShpProfile_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, channel_id, cmd, &chan_shp_profile));
    }

    SetQMgrPortShpCtl(V, shpPtrMax_f, &port_shp_ctl, MCHIP_CAP(SYS_CAP_PER_DP_CHANNEL_NUM) * 2 - 1);
    SetQMgrPortShpCtl(V, shpPtrMin_f, &port_shp_ctl, 0);
    SetQMgrPortShpCtl(V, shpRefreshDis_f, &port_shp_ctl, 0);
    SetQMgrPortShpCtl(V, shpTickInterval_f, &port_shp_ctl, 1);
    cmd = DRV_IOW(QMgrPortShpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &port_shp_ctl));

    SetDsEpeHeaderEditChanAqmScanCtl(V, aqmPortScanEn_f, &aqm_port_scan_ctl, 1);
    SetDsEpeHeaderEditChanAqmScanCtl(V, aqmPortScanInterval_f, &aqm_port_scan_ctl, 10);
    SetDsEpeHeaderEditChanAqmScanCtl(V, aqmPortScanPtrMax_f, &aqm_port_scan_ctl, 51); /*network channel:26*2-1*/
    SetDsEpeHeaderEditChanAqmScanCtl(V, aqmPortScanPtrPhyMax_f, &aqm_port_scan_ctl, 51);
    cmd = DRV_IOW(DsEpeHeaderEditChanAqmScanCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &aqm_port_scan_ctl));

    /*need per channel update*/
    SetEpeHeaderEditChanAqmUpdateCtl(V, chanAqmUpdateEn_f, &aqm_port_update_ctl, 1);
    SetEpeHeaderEditChanAqmUpdateCtl(V, ipg_f, &aqm_port_update_ctl, 0);
    cmd = DRV_IOW(EpeHeaderEditChanAqmUpdateCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &aqm_port_update_ctl));

    cmd = DRV_IOR(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_ctl));
    SetEpeHdrAdjustCtl(V, aqmPortEn_f, &epe_hdr_ctl, 1);
    cmd = DRV_IOW(EpeHdrAdjustCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &epe_hdr_ctl));

    cmd = DRV_IOR(QMgrRdPktUnitCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pkt_unit));
    SetQMgrRdPktUnitCtl(V, pktLenUnit_f, &pkt_unit, 125);
    cmd = DRV_IOW(QMgrRdPktUnitCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &pkt_unit));

    return CTC_E_NONE;
}

STATIC int32
_sys_at_shape_init_net_chan_credit(uint8 lchip, uint32 enable)
{
    sys_port_info_t port_info;
    uint16 lport = 0;
    uint8  gchip = 0;

    sys_usw_get_gchip_id(lchip, &gchip);

    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); lport++)
    {
        CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, 0, &port_info));
        if (SYS_DMPS_INVALID_U16 == port_info.sub_chan_id)
        {
            continue;
        }

        CTC_ERROR_RETURN(sys_at_sch_set_wrr_en(lchip, &port_info, enable));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_map_ecnmark_rate_user_to_hw(uint8 lchip,
                                            uint32 *hw_rate,
                                            uint32 user_rate)
{
    /*
    cfgSlice0RefDivEpeHdrEditAqmScanPulse: 100us
    updaterate:
    1. userrate*1000 --> Kbps to bps
    2. userrate*1000 * 100000 / 1000000000 -- >  userrate / 10 --> 100us sum bits
    3. / 8 bit-->byte
    */
    *hw_rate = (uint64)user_rate * 1000 * 100000 / 1000000000 / 8;

    return CTC_E_NONE;
}
STATIC int32
_sys_at_qos_map_ecnmark_rate_hw_to_user(uint8 lchip,
                                            uint32 hw_rate,
                                            uint32* user_rate)
{
    /*
    cfgSlice0RefDivEpeHdrEditAqmScanPulse: 100us

    */
    *user_rate = hw_rate * 8 * 10;

    return CTC_E_NONE;
}

STATIC int32
_sys_at_qos_shp_set_ecnmark_rate(uint8 lchip, uint16 channel,uint32 ecn_mark_rate)
{
    uint32 cmd                     = 0;
    uint32 update_rate = 0;
    uint16 sub_chan = 0;
    uint8 dp_chan = 0;
    uint8 dp_id = 0;
    uint8 pp_id = 0;
    uint16 index = 0;
    DsEpeHeaderEditChanAqmConfig_m aqm_port_cfg;
    DsEpeHeaderEditChanAqmThrd_m aqm_port_thrd;

    CTC_ERROR_RETURN(_sys_at_qos_map_ecnmark_rate_user_to_hw(lchip, &update_rate, ecn_mark_rate));

    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    dp_id = SYS_DP_BY_SUB_CHAN(sub_chan);
    pp_id = SYS_PP_BY_SUB_CHAN(sub_chan);
    lchip = SYS_PP_BASE(lchip) + pp_id;
    dp_chan = SYS_DP_CHAN_BY_SUB_CHAN(sub_chan);
    index = (dp_chan << 1) + dp_id;
    cmd = DRV_IOR(DsEpeHeaderEditChanAqmConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &aqm_port_cfg));
    SetDsEpeHeaderEditChanAqmConfig(V, aqmPortRate_f, &aqm_port_cfg, update_rate);
    cmd = DRV_IOW(DsEpeHeaderEditChanAqmConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &aqm_port_cfg));

    cmd = DRV_IOR(DsEpeHeaderEditChanAqmThrd_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &aqm_port_thrd));
    SetDsEpeHeaderEditChanAqmThrd(V, aqmPortThrdHigh_f, &aqm_port_thrd, (ecn_mark_rate ? update_rate : 0xFFFFFFFF));
    SetDsEpeHeaderEditChanAqmThrd(V, aqmPortThrdLow_f, &aqm_port_thrd, (ecn_mark_rate ? update_rate/2 : 0xFFFFFFFF));
    cmd = DRV_IOW(DsEpeHeaderEditChanAqmThrd_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &aqm_port_thrd));
    return CTC_E_NONE;
}
STATIC int32
_sys_at_qos_shp_get_ecnmark_rate(uint8 lchip, uint16 channel,uint32* ecn_mark_rate)
{
    uint32 cmd                     = 0;
    uint32 update_rate = 0;
    uint16 sub_chan = 0;
    uint8 dp_chan = 0;
    uint8 dp_id = 0;
    uint8 pp_id = 0;
    uint16 index = 0;
    DsEpeHeaderEditChanAqmConfig_m aqm_port_cfg;
    DsEpeHeaderEditChanAqmThrd_m aqm_port_thrd;

    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    dp_id = SYS_DP_BY_SUB_CHAN(sub_chan);
    pp_id = SYS_PP_BY_SUB_CHAN(sub_chan);
    lchip = SYS_PP_BASE(lchip) + pp_id;
    dp_chan = SYS_DP_CHAN_BY_SUB_CHAN(sub_chan);
    index = (dp_chan << 1) + dp_id;

    cmd = DRV_IOR(DsEpeHeaderEditChanAqmThrd_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &aqm_port_thrd));
    if (0xFFFFFFFF == GetDsEpeHeaderEditChanAqmThrd(V, aqmPortThrdHigh_f, &aqm_port_thrd))
    {
        *ecn_mark_rate = 0;
        return CTC_E_NONE;
    }
    cmd = DRV_IOR(DsEpeHeaderEditChanAqmConfig_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index, DRV_CMD_PP_EN(cmd), &aqm_port_cfg));
    update_rate = GetDsEpeHeaderEditChanAqmConfig(V, aqmPortRate_f, &aqm_port_cfg);
    CTC_ERROR_RETURN(_sys_at_qos_map_ecnmark_rate_hw_to_user(lchip, update_rate, ecn_mark_rate));

    return CTC_E_NONE;
}

STATIC bool
_sys_at_queue_shp_get_channel_pps_enbale(uint8 lchip, uint16 chand_id)
{
    uint32 cmd = 0;
    uint32 pps_en = 0;
    uint16 sub_chan = 0;
    uint16 pp_chan = 0;
    uint32 field_val[2] = {0};

    if(SYS_IS_NETWORK_CHANNEL(chand_id))
    {
        QMgrGrpPpsModeCtlUc_m qmgr_ctl_uc;
        CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, chand_id, &sub_chan));
        pp_chan = SYS_PP_CHAN_BY_SUB_CHAN(sub_chan);

        cmd = DRV_IOR(QMgrGrpPpsModeCtlUc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, DRV_CMD_PP_EN(cmd), &qmgr_ctl_uc));
        GetQMgrGrpPpsModeCtlUc(A, ppsMode_f, &qmgr_ctl_uc, field_val);

        pps_en =CTC_BMP_ISSET(field_val, pp_chan) ? 1 : 0;
    }
    if ((p_usw_queue_master[lchip]->shp_pps_en &&
        (chand_id == MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0)
        || chand_id == MCHIP_CAP(SYS_CAP_CHANID_DMA_RX1)
        || chand_id == MCHIP_CAP(SYS_CAP_CHANID_DMA_RX2)
        || chand_id == MCHIP_CAP(SYS_CAP_CHANID_DMA_RX3)))
        || pps_en)
    {
        return TRUE;
    }
    else if(DRV_FROM_TMM(lchip) && p_usw_queue_master[lchip]->shp_pps_en &&
        (chand_id == MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC0) || chand_id == MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC1)
        || chand_id == MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC2) || chand_id == MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC3)))
    {
        uint8  index = 0;
        uint8  is_network = 0;
        uint16 lport = 0;

        index = chand_id - (chand_id > MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC1) ? (MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC2) - 2) : MCHIP_CAP(SYS_CAP_CHANID_CPU_MAC0));
        if (MCHIP_DMPS(lchip)->cpumac_get_lport_info_by_inner_idx)
        {
            MCHIP_DMPS(lchip)->cpumac_get_lport_info_by_inner_idx(lchip,index,&lport,&is_network);
        }

        return is_network ? FALSE : TRUE;
    }
    else
    {
        return FALSE;
    }

    return FALSE;
}
STATIC int32
_sys_at_queue_shp_set_channel_shape_enable(uint8 lchip, uint16 channel,
                                             ctc_qos_shape_port_t* p_shape)
{
    uint8  is_pps = 0;

    CTC_PTR_VALID_CHECK(p_shape);
    CTC_MAX_VALUE_CHECK(p_shape->ecn_mark_rate, SYS_QOS_SHAPE_MAX_ECNMARK_RATE);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    is_pps = _sys_at_queue_shp_get_channel_pps_enbale(lchip, channel);
    if(1 == is_pps)
    {
        /*max_port_rate / (64 + 20)*/
        CTC_MAX_VALUE_CHECK(p_shape->pir, MCHIP_CAP(SYS_CAP_QOS_SHP_RATE_PPS));
    }
    else
    {
        CTC_MAX_VALUE_CHECK(p_shape->pir, MCHIP_CAP(SYS_CAP_QOS_SHP_RATE));
    }

    CTC_ERROR_RETURN(sys_at_shape_add_chan_shp_to_asic(lchip, channel, p_shape->pir, p_shape->pbs, is_pps, 1));
    if (SYS_IS_NETWORK_CHANNEL(channel))
    {
        CTC_ERROR_RETURN(_sys_at_qos_shp_set_ecnmark_rate(lchip, channel, p_shape->ecn_mark_rate));
    }
    return CTC_E_NONE;
}
STATIC int32
_sys_at_queue_shp_set_channel_shape_disable(uint8 lchip, uint16 channel,
                                                            ctc_qos_shape_port_t* p_shape)
{
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    CTC_MAX_VALUE_CHECK(p_shape->ecn_mark_rate, SYS_QOS_SHAPE_MAX_ECNMARK_RATE);

    CTC_ERROR_RETURN(sys_at_shape_add_chan_shp_to_asic(lchip, channel, p_shape->pir, p_shape->pbs, 0, 0));
    if (SYS_IS_NETWORK_CHANNEL(channel))
    {
        CTC_ERROR_RETURN(_sys_at_qos_shp_set_ecnmark_rate(lchip, channel, p_shape->ecn_mark_rate));
    }
    return CTC_E_NONE;
}
STATIC int32
_sys_at_queue_shp_set_channel_shape(uint8 lchip, ctc_qos_shape_port_t* p_shape)
{
    uint16 channel = 0;
    uint32 chan_tmp = 0;

    if (SYS_MAP_CTC_GPORT_TO_PORT_TYPE(p_shape->gport) == CTC_GPORT_TYPE_DMA)
    {
        channel = MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0);
    }
    else
    {
        sys_usw_dmps_port_info_t dmps_port_info = {0};
        dmps_port_info.gport = p_shape->gport;
        dmps_port_info.index = CTC_MAP_GPORT_TO_MCHAN_IDX(p_shape->gport);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_tmp));
        channel = chan_tmp;
    }

    if (p_shape->pir == CTC_MAX_UINT32_VALUE)
    {
        CTC_ERROR_RETURN(sys_at_qos_set_port_shp_base_pkt_en(lchip, p_shape->gport, p_shape->pps_en));
        return CTC_E_NONE;
    }

    CTC_MAX_VALUE_CHECK(channel, MCHIP_CAP(SYS_CAP_CHANID_MAX) - 1);
/*DMA TODO*/
    if (p_shape->enable)
    {
        CTC_ERROR_RETURN(
            _sys_at_queue_shp_set_channel_shape_enable(lchip, channel, p_shape));
    }
    else
    {
        CTC_ERROR_RETURN(
            _sys_at_queue_shp_set_channel_shape_disable(lchip, channel, p_shape));
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_at_queue_shp_get_channel_shape(uint8 lchip, ctc_qos_shape_port_t* p_shape)
{
    uint16 channel = 0;
    uint32 token_thrd = 0;
    uint32 token_rate = 0;
    uint32 chan_tmp = 0;
    uint8 is_pps = 0;
    uint8 enable = 0;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (SYS_MAP_CTC_GPORT_TO_PORT_TYPE(p_shape->gport) == CTC_GPORT_TYPE_DMA)
    {
        channel = MCHIP_CAP(SYS_CAP_CHANID_DMA_RX0);
    }
    else
    {
        sys_usw_dmps_port_info_t dmps_port_info = {0};
        dmps_port_info.gport = p_shape->gport;
        dmps_port_info.index = CTC_MAP_GPORT_TO_MCHAN_IDX(p_shape->gport);
        CTC_ERROR_RETURN(sys_usw_port_api_get_dmps_property(lchip, &dmps_port_info, SYS_PORT_API_DMPS_PROP_CHAN_ID, &chan_tmp));
        channel = chan_tmp;
    }

    CTC_MAX_VALUE_CHECK(channel, MCHIP_CAP(SYS_CAP_CHANID_MAX) - 1);
/*DMA TODO*/
    CTC_ERROR_RETURN(sys_at_shape_get_port_shape_profile(lchip, channel, &token_rate, &token_thrd, &is_pps, &enable));
    p_shape->enable = enable;
    p_shape->pps_en = is_pps;
    p_shape->pir = token_rate;
    p_shape->pbs = token_thrd;
    if (SYS_IS_NETWORK_CHANNEL(channel))
    {
        CTC_ERROR_RETURN(_sys_at_qos_shp_get_ecnmark_rate(lchip, channel, &p_shape->ecn_mark_rate));
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_shp_set_queue_shape_enable(uint8 lchip, uint16 queue_id,
                                           ctc_qos_shape_queue_t* p_shape)
{
    sys_queue_node_t* p_sys_queue_node = NULL;

    uint8 is_pps = 0;
    uint16 channel = 0;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(p_shape);

    CTC_ERROR_RETURN(sys_at_queue_get_channel_by_queue_id(lchip, queue_id, &channel));
    is_pps = _sys_at_queue_shp_get_channel_pps_enbale(lchip, channel);

    if (is_pps)
    {
        CTC_MAX_VALUE_CHECK(p_shape->pir, MCHIP_CAP(SYS_CAP_QOS_SHP_RATE_PPS));
        CTC_MAX_VALUE_CHECK(p_shape->cir, MCHIP_CAP(SYS_CAP_QOS_SHP_RATE_PPS));
    }
    else
    {
        CTC_MAX_VALUE_CHECK(p_shape->pir, MCHIP_CAP(SYS_CAP_QOS_SHP_RATE));
        CTC_MAX_VALUE_CHECK(p_shape->cir, MCHIP_CAP(SYS_CAP_QOS_SHP_RATE));
    }

    p_sys_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_sys_queue_node)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }
    /*p_sys_queue_node->type = p_shape->queue.queue_type;*/
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "queue_id:%d\n", queue_id);

    CTC_ERROR_RETURN(sys_at_shape_add_que_shp_to_asic(lchip, p_sys_queue_node, (void *)p_shape, is_pps));
    p_sys_queue_node->shp_en = 1;

    return CTC_E_NONE;
}


int32
_sys_at_queue_shp_set_queue_shape_disable(uint8 lchip, uint16 queue_id,
                                                                    ctc_qos_shape_queue_t* p_shape)
{
    sys_queue_node_t* p_sys_queue_node = NULL;

    p_sys_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_sys_queue_node)
    {
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }
    CTC_ERROR_RETURN(sys_at_shape_add_que_shp_to_asic(lchip, p_sys_queue_node, (void *)p_shape, 0));
    p_sys_queue_node->shp_en = 0;

    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_shp_set_queue_shape(uint8 lchip, ctc_qos_shape_queue_t* p_shape)
{
    uint16 queue_id = 0;

    /*get queue_id*/

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "p_shape->queue_id = %d\n", p_shape->queue.queue_id);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "p_shape->queue_type = %d\n", p_shape->queue.queue_type);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "p_shape->enable = %d\n", p_shape->enable);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "p_shape->gport = %d\n", p_shape->queue.gport);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "p_shape->pir = %d\n", p_shape->pir);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "p_shape->cir = %d\n", p_shape->cir);

    CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip,  &p_shape->queue, &queue_id));

    if (p_shape->enable)
    {
        CTC_ERROR_RETURN(_sys_at_queue_shp_set_queue_shape_enable(lchip, queue_id, p_shape));
    }
    else
    {
        CTC_ERROR_RETURN(_sys_at_queue_shp_set_queue_shape_disable(lchip, queue_id, p_shape));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_at_queue_shp_get_queue_shape(uint8 lchip, ctc_qos_shape_queue_t* p_shape)
{
    uint16 queue_id = 0;
    sys_queue_node_t* p_queue_node = NULL;

    CTC_ERROR_RETURN(sys_at_queue_get_queue_id(lchip, &p_shape->queue,
                                                           &queue_id));
    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node)
    {
        return CTC_E_INVALID_PARAM;
    }
    p_shape->cir = SYS_SHAPE_DEFAULT_RATE;
    p_shape->cbs = SYS_SHAPE_DEFAULT_THRD;
    p_shape->pir = SYS_SHAPE_DEFAULT_RATE;
    p_shape->pbs = SYS_SHAPE_DEFAULT_THRD;

    CTC_ERROR_RETURN(sys_at_shape_get_que_shape_profile(lchip, queue_id, p_queue_node->offset, (void *)p_shape));
    return CTC_E_NONE;
}


#define ______SYS_AT_QUEUE_SHAPE_API______
int32
sys_at_qos_set_port_shp_base_pkt_en(uint8 lchip, uint32 gport, uint8 enable)
{
    uint32 cmd = 0;
    uint32 wrr_en = 0;
    uint32 field_val = 0;
    uint16 queue_base = 0;
    uint16 loop = 0;
    uint16 lport = 0;
    uint8 index = 0;
    uint8 step = 0;
    uint8 pp_chan = 0;
    uint8 is_switch = 0;
    ds_t ds;
    sys_port_info_t port_info;
    sys_queue_node_t* p_sys_queue_node = NULL;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, " gport : %d \n", gport);
    if (!SYS_GPORT_IS_NETWORK_PORT(gport))
    {
        return CTC_E_INVALID_GLOBAL_PORT;
    }

    sal_memset(&port_info, 0, sizeof(sys_port_info_t));
    lport = CTC_MAP_GPORT_TO_LPORT(gport);
    index = CTC_MAP_GPORT_TO_MCHAN_IDX(gport);

    CTC_ERROR_RETURN(sys_usw_port_api_get_com_info(lchip, lport, index, &port_info));

    pp_chan = SYS_AT_QOS_ENCOD_PP_CHAN(port_info.sub_chan_id, port_info.dp_id);
    SYS_QOS_LCHIP_CONVERT(lchip, port_info.pp_id);

    /*1. check the switch status*/
    field_val = enable ? 1 : 0;
    CTC_ERROR_RETURN(sys_at_sch_get_wrr_en(lchip, &port_info, &wrr_en));
    is_switch = (field_val == wrr_en) ? 0 : 1;
    if (!is_switch)
    {
        return CTC_E_NONE;
    }

    /*2. switch wrr mode means switch bps/pps mode on channel*/
    CTC_ERROR_RETURN(sys_at_sch_set_wrr_en(lchip, &port_info, enable));

    /*3. flush chan shape as default*/
    cmd = DRV_IOR(DsQMgrPortShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &ds));
    SetDsQMgrPortShpProfile(V, tokenGran_f  , &ds, 7);
    SetDsQMgrPortShpProfile(V, tokenRate_f, &ds, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE));
    SetDsQMgrPortShpProfile(V, tokenThrd_f  , &ds, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD));
    cmd = DRV_IOW(DsQMgrPortShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &ds));

    /*4. disable queue shape*/
    queue_base = pp_chan * MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN) + port_info.pp_id * MCHIP_CAP(SYS_CAP_QOS_BASE_QUEUE_GRP_NUM);
    for (loop = queue_base; loop < (queue_base + MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_GRP)); loop++)
    {
        p_sys_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, loop);
        if (NULL == p_sys_queue_node)
        {
            SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
            return CTC_E_NOT_EXIST;
        }
        p_sys_queue_node->shp_en = 0;
    }

    /*4.1. flush queue pir as default*/
    step = DsQMgrCosGrpShpProfile_g_1_shpProfile_ppsMode_f - DsQMgrCosGrpShpProfile_g_0_shpProfile_ppsMode_f;
    cmd = DRV_IOR(DsQMgrCosGrpShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &ds));
    for (loop = 0; loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_GRP); loop++)
    {
        SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenRate_f + loop * step, &ds, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE));
        SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenThrd_f + loop * step, &ds, MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD));
        SetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenGran_f + loop * step, &ds, 7);
    }
    cmd = DRV_IOW(DsQMgrCosGrpShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &ds));

    /*4.2 flush queue cir as default*/
    step = DsQMgrCosGrpShpProfile0_g_1_shpProfile0_ppsMode_f - DsQMgrCosGrpShpProfile0_g_0_shpProfile0_ppsMode_f;
    cmd = DRV_IOR(DsQMgrCosGrpShpProfile0_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &ds));
    for (loop = 0; loop < MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_GRP); loop++)
    {
        SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenRate_f + loop * step, &ds, 0);
        SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenThrd_f + loop * step, &ds, 0);
        SetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenGran_f + loop * step, &ds, 0);
    }
    cmd = DRV_IOW(DsQMgrCosGrpShpProfile0_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &ds));

    return CTC_E_NONE;
}

int32
sys_at_qos_set_glb_port_shp_base_pkt_en(uint8 lchip, uint8 enable)
{
    int32  ret   = CTC_E_NONE;
    uint32 gport = 0;
    uint16 lport = 0;
    uint8  gchip = 0;

    sys_usw_get_gchip_id(lchip, &gchip);

    for (lport = 0; lport < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); lport++)
    {
        gport = CTC_MAP_LPORT_TO_GPORT(gchip, lport);

        ret = sys_at_qos_set_port_shp_base_pkt_en(lchip, gport, enable);

        if (ret && CTC_E_INVALID_GLOBAL_PORT != ret)
        {
            return ret;
        }
    }
    return CTC_E_NONE;
}
int32
sys_at_shape_get_port_shape_profile(uint8 lchip, uint16 channel, uint32* rate, uint32* thrd,
                                                              uint8* pps_en, uint8* p_shp_en)
{
    uint32 cmd;
    uint32 token_thrd = 0;
    uint8  token_gran = 0;
    uint32 token_rate = 0;
    uint8  is_pps = 0;
    DsQMgrPortShpProfile_m  port_shp_profile;
    uint16  sub_chan = 0;
    uint8 pp_chan = 0;

    SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_ERROR_RETURN(sys_at_get_sub_channel_by_channel(lchip, channel, &sub_chan));
    pp_chan = SYS_PP_CHAN_BY_SUB_CHAN(sub_chan);
    SYS_QOS_LCHIP_CONVERT(lchip, SYS_PP_BY_SUB_CHAN(sub_chan));
    cmd = DRV_IOR(DsQMgrPortShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, pp_chan, DRV_CMD_PP_EN(cmd), &port_shp_profile));

    is_pps = _sys_at_queue_shp_get_channel_pps_enbale(lchip, channel);
    token_gran = GetDsQMgrPortShpProfile(V, tokenGran_f, &port_shp_profile);
    token_rate = GetDsQMgrPortShpProfile(V, tokenRate_f, &port_shp_profile);
    token_thrd = GetDsQMgrPortShpProfile(V, tokenThrd_f, &port_shp_profile);

    *p_shp_en = (token_rate != MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE)) || (token_thrd != MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD))
                || (token_gran != 7);

    *pps_en = is_pps;

    sys_at_shape_map_profile_hw_to_user(lchip, token_rate, token_thrd, is_pps, token_gran, rate, thrd);

    return CTC_E_NONE;
}
int32
sys_at_shape_get_que_shape_profile(uint8 lchip, uint16 queue_id, uint16 queue_offset, void* p_shape)
{

    uint32 cmd = 0;
    uint16 group_id = 0;
    uint8  gran_lvl = 0;
    uint8  gran_lvl_cir = 0;
    uint8  prof_step = 0;
    uint8  shp_en = 0;
    uint8  is_pps = 0;
    uint32 token_rate = 0;
    uint32 token_thrd = 0;
    uint8  shp_en_cir = 0;
    uint32 token_rate_cir = 0;
    uint32 token_thrd_cir = 0;
    uint16 channel = 0;
    ds_t ds;
    ctc_qos_shape_queue_t* p_que_shape = (ctc_qos_shape_queue_t*)p_shape;
    sys_queue_node_t* p_queue_node = NULL;

    p_queue_node = ctc_vector_get(p_usw_queue_master[lchip]->queue_vec, queue_id);
    if (NULL == p_queue_node)
    {
        return CTC_E_NOT_EXIST;
    }

    SYS_QOS_LCHIP_CONVERT(lchip, p_queue_node->pp_id);
    CTC_ERROR_RETURN(sys_at_get_channel_by_sub_channel(lchip, p_queue_node->dp_id, p_queue_node->sub_chan, &channel));
    if (SYS_QUEUE_TYPE_EUNIT == p_queue_node->type)
    {
        group_id = SYS_DMA_SUB_CHAN; /*dma sub channel id*/
        queue_offset = queue_id - (MCHIP_CAP(SYS_CAP_QOS_QUEUE_BASE_EXCP) + MCHIP_CAP(SYS_CAP_CPU_REASON_GRP_BASE_EUNIT) * MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM));
        queue_offset &= 0xF;
    }
    else if (SYS_QUEUE_TYPE_EXCP == p_queue_node->type || SYS_QUEUE_TYPE_EXCP_UC == p_queue_node->type)
    {
        SYS_AT_GROUP_ID(group_id, p_queue_node);
        queue_offset = p_queue_node->offset % MCHIP_CAP(SYS_CAP_REASON_GRP_QUEUE_NUM);
    }
    else
    {
        SYS_AT_GROUP_ID(group_id, p_queue_node);
        queue_offset = queue_id % MCHIP_CAP(SYS_CAP_QOS_QUEUE_NUM_PER_CHAN);
    }

    prof_step = DsQMgrCosGrpShpProfile_g_1_shpProfile_tokenRate_f - DsQMgrCosGrpShpProfile_g_0_shpProfile_tokenRate_f;

    cmd = DRV_IOR(DsQMgrCosGrpShpProfile_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, DRV_CMD_PP_EN(cmd), &ds));
    token_rate = GetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenRate_f + prof_step * queue_offset, &ds);
    token_thrd = GetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenThrd_f + prof_step * queue_offset, &ds);
    gran_lvl = GetDsQMgrCosGrpShpProfile(V, g_0_shpProfile_tokenGran_f + prof_step * queue_offset, &ds);
    is_pps = _sys_at_queue_shp_get_channel_pps_enbale(lchip, channel);

    if (SYS_QUEUE_TYPE_NORMAL == p_queue_node->type || SYS_QUEUE_TYPE_EUNIT == p_queue_node->type)
    {
        prof_step = DsQMgrCosGrpShpProfile0_g_1_shpProfile0_tokenGran_f - DsQMgrCosGrpShpProfile0_g_0_shpProfile0_tokenGran_f;

        cmd = DRV_IOR(DsQMgrCosGrpShpProfile0_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, group_id, DRV_CMD_PP_EN(cmd), &ds));
        token_rate_cir = GetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenRate_f + prof_step * queue_offset, &ds);
        token_thrd_cir = GetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenThrd_f + prof_step * queue_offset, &ds);
        gran_lvl_cir = GetDsQMgrCosGrpShpProfile0(V, g_0_shpProfile0_tokenGran_f + prof_step * queue_offset, &ds);
    }

    shp_en = (token_rate != MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_RATE)) || (token_thrd != MCHIP_CAP(SYS_CAP_QOS_SHP_TOKEN_THRD))
                || (gran_lvl != 7);
    shp_en_cir = (token_rate_cir != 0) || (token_thrd_cir != 0) || (gran_lvl_cir != 0);
    p_que_shape->enable = shp_en || shp_en_cir;
    p_que_shape->pps_en = is_pps;

    sys_at_shape_map_profile_hw_to_user(lchip, token_rate, token_thrd, is_pps, gran_lvl, &p_que_shape->pir, &p_que_shape->pbs);
    sys_at_shape_map_profile_hw_to_user(lchip, token_rate_cir, token_thrd_cir, is_pps, gran_lvl_cir, &p_que_shape->cir, &p_que_shape->cbs);

    return CTC_E_NONE;
}

int32
sys_at_qos_set_shape(uint8 lchip, ctc_qos_shape_t* p_shape)
{
    CTC_PTR_VALID_CHECK(p_shape);
    switch (p_shape->type)
    {
    case CTC_QOS_SHAPE_PORT:
        CTC_ERROR_RETURN(
                _sys_at_queue_shp_set_channel_shape(lchip, &p_shape->shape.port_shape));
        break;

    case CTC_QOS_SHAPE_QUEUE:
        CTC_ERROR_RETURN(
            _sys_at_queue_shp_set_queue_shape(lchip, &p_shape->shape.queue_shape));
        break;

    case CTC_QOS_SHAPE_GROUP:
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " API or some feature is not supported \n");
        return CTC_E_NOT_SUPPORT;
    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_at_qos_get_shape(uint8 lchip, ctc_qos_shape_t* p_shape)
{
    CTC_PTR_VALID_CHECK(p_shape);

    switch (p_shape->type)
    {
    case CTC_QOS_SHAPE_PORT:
        CTC_ERROR_RETURN(_sys_at_queue_shp_get_channel_shape(lchip, &p_shape->shape.port_shape));
        break;

    case CTC_QOS_SHAPE_QUEUE:
        CTC_ERROR_RETURN(_sys_at_queue_shp_get_queue_shape(lchip, &p_shape->shape.queue_shape));
        break;

    case CTC_QOS_SHAPE_GROUP:
        SYS_QOS_QUEUE_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " API or some feature is not supported \n");
        return CTC_E_NOT_SUPPORT;
    default:
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_at_queue_shape_init(uint8 lchip)
{
    uint8  lchip_tmp = lchip;
    uint8  pp_id = 0;
    uint32 cmd = 0;
    QMgrCtl_m  qmgr_ctl;
    QMgrShpCtl_m qmgr_shp_ctl;
    RefDivSlice0PPPulse_m shp_pulse;
    ds_t ds;
    sys_qos_rate_granularity_t shp_gran[SYS_SHP_GRAN_RANAGE_NUM] = {{10000,      10},
                                                                    {20000,      20},
                                                                    {40000,      40},
                                                                    {80000,      80},
                                                                    {160000,     160},
                                                                    {320000,     320},
                                                                    {640000,     640},
                                                                    {800000,     1280}};
    sal_memset(&qmgr_ctl, 0, sizeof(QMgrCtl_m));
    sal_memset(&qmgr_shp_ctl, 0, sizeof(QMgrShpCtl_m));
    sal_memset(&shp_pulse, 0, sizeof(RefDivSlice0PPPulse_m));

    sal_memcpy(p_usw_queue_master[lchip]->que_shp_gran, shp_gran,
               SYS_SHP_GRAN_RANAGE_NUM * sizeof(sys_qos_rate_granularity_t));

    CTC_ERROR_RETURN(_sys_at_shape_init_queue_shp(lchip));
    CTC_ERROR_RETURN(_sys_at_shape_init_group_shp(lchip));
    CTC_ERROR_RETURN(_sys_at_shape_init_chan_shp(lchip));
    CTC_ERROR_RETURN(sys_at_sch_set_dma_chan_credit(lchip, TRUE));
    CTC_ERROR_RETURN(sys_at_sch_set_ecpu_chan_credit(lchip, FALSE));
    CTC_ERROR_RETURN(_sys_at_shape_init_net_chan_credit(lchip, FALSE));

    p_usw_queue_master[lchip]->shp_pps_en = 1;

    for (pp_id = 0; pp_id < SYS_PP_NUM(lchip); pp_id++)
    {
        SYS_QOS_LCHIP_CONVERT(lchip_tmp, pp_id);
        cmd = DRV_IOR(QMgrCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, 0, DRV_CMD_PP_EN(cmd), &qmgr_ctl));
        SetQMgrCtl(V, cosShpEn_f, &qmgr_ctl, 1);
        SetQMgrCtl(V, cosShpEn0_f, &qmgr_ctl, 1);
        if (SYS_CORE_PP_BASE(lchip_tmp) == lchip_tmp)
        {
            SetQMgrCtl(V, dmaChanId_f, &qmgr_ctl, SYS_DMA_SUB_CHAN);
            SetQMgrCtl(V, dmaExtEn_f, &qmgr_ctl, 1);
        }
        SetQMgrCtl(V, l0NodeShpEn_f, &qmgr_ctl, 1);
        SetQMgrCtl(V, portShpEn_f, &qmgr_ctl, 1);
        cmd = DRV_IOW(QMgrCtl_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip_tmp, 0, DRV_CMD_PP_EN(cmd), &qmgr_ctl));
    }

    cmd = DRV_IOR(QMgrShpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qmgr_shp_ctl));
    SetQMgrShpCtl(V, gran_0_pktLenUnit_f, &qmgr_shp_ctl, 320000);
    SetQMgrShpCtl(V, gran_1_pktLenUnit_f, &qmgr_shp_ctl, 160000);
    SetQMgrShpCtl(V, gran_2_pktLenUnit_f, &qmgr_shp_ctl, 64000);
    SetQMgrShpCtl(V, gran_3_pktLenUnit_f, &qmgr_shp_ctl, 32000);
    SetQMgrShpCtl(V, gran_4_pktLenUnit_f, &qmgr_shp_ctl, 8000);
    SetQMgrShpCtl(V, gran_5_pktLenUnit_f, &qmgr_shp_ctl, 1000);
    SetQMgrShpCtl(V, gran_6_pktLenUnit_f, &qmgr_shp_ctl, 400);
    SetQMgrShpCtl(V, gran_7_pktLenUnit_f, &qmgr_shp_ctl, 200);
    cmd = DRV_IOW(QMgrShpCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &qmgr_shp_ctl));

    p_usw_queue_master[lchip]->que_shp_update_freq = 320000;
    p_usw_queue_master[lchip]->chan_shp_update_freq = 320000;

    /*Freq: 320k
    pulse : 0x1e748
 156250000/320000.0 = 488.28125, hex(488-1) = 0x1e7, 0.28125 * 256 = 0x48
     */

    cmd = DRV_IOR(QMgrDeqMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    SetQMgrDeqMiscCtl(V, cfgShpRePickUseGrpAvailEn_f, &ds, 0);
    SetQMgrDeqMiscCtl(V, cfgShpRePickUseShpStateEn_f, &ds, 0);
    cmd = DRV_IOW(QMgrDeqMiscCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ds));
    cmd = DRV_IOR(RefDivSlice0PPPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &shp_pulse));
    SetRefDivSlice0PPPulse(V, cfgSlice0RefDivQMgrDeqShpPulse_f, &shp_pulse, 0x1e748);
    SetRefDivSlice0PPPulse(V, cfgSlice0ResetDivQMgrDeqShpPulse_f, &shp_pulse, 0);
    cmd = DRV_IOW(RefDivSlice0PPPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &shp_pulse));
    cmd = DRV_IOW(RefDivSlice1PPPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &shp_pulse));
    cmd = DRV_IOW(RefDivSlice2PPPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &shp_pulse));
    cmd = DRV_IOW(RefDivSlice3PPPulse_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &shp_pulse));
    return CTC_E_NONE;
}

int32
sys_at_queue_shape_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}


#endif
